Ledger foundations

Everything below is generated from one set of files: tokens/renewcms.css (Tailwind @theme, :root, .dark, article content styles), tokens/ui.config.ts (Nuxt UI colors, icons and component overrides) and tokens/vite.config.ts. The tables on this page read those files, so they can't drift.

Logo

The mark is a white R on a black square, drawn on a 16-pixel grid so it stays sharp as a favicon. It keeps the same geometry at every size. In dark mode the black square gets a 1 px #444 edge so it doesn't disappear into the background. The wordmark pairs the mark with RenewCMS in Plex Sans Semibold, with the text set at 0.6× the mark's height.

RenewCMS
16
32
64
128, app icon source for 180 / 512
Articles · RenewCMS
RenewCMS
16
32
64
128
Articles · RenewCMS

Favicon file: brand/favicon.svg. The 1 px edge switches on with prefers-color-scheme: dark. Keep clear space of at least half the mark's height around it. The R is never recolored or placed on sand.

Color scales

Seven Tailwind color scales, each mapped to a Nuxt UI alias. The ink, chalk and sand scales are built on your brand values. The four semantic scales are new and deliberately muted: evenly spaced oklch lightness steps with low chroma, so they sit comfortably next to ink and sand.

{{ sc.alias }}{{ sc.name }}{{ sc.note }}
{{ st.k }}{{ st.hex }}

Theme variables

Every --ui-* variable Nuxt UI reads, for both themes. Surfaces are white. The #fafafa brand background is the page canvas behind them. The theme follows the system setting until the owner picks Light or Dark from the user menu, and that choice is stored by Nuxt UI's color mode.

VariableUsed forLightDark
{{ v.name }}{{ v.use }} {{ v.lr }} {{ v.lh }} {{ v.dr }} {{ v.dh }}

Contrast checks

Each ratio is computed from the variables above against WCAG 2.2 AA: 4.5:1 for text and 3:1 for control edges and focus rings. Soft alerts are measured against a 10% tint of the color over the surface, which is how Nuxt UI renders them. {{ passSummary }}

PairNeedsLightDark
{{ c.label }}{{ c.need }} Aa{{ c.light.ratio }} Aa{{ c.dark.ratio }}

Typography

The interface uses IBM Plex Sans in three weights: 400, 500 and 600. IDs, paths, counters and code are set in IBM Plex Mono. Sizes replace Tailwind's text-* defaults. On screens narrower than md, form fields use 16 px so iOS doesn't zoom in when a field gets focus.

Before and after: the Rue Verte kitchen
{{ t.name }} · {{ t.size }} / {{ t.lh }} · {{ t.w }}{{ t.use }}
GET /v1/article/12 · 8 412 / 10 000
font-mono · 13px / 20px · 400Code, paths, IDs, counters

Article content uses a separate scale in Source Serif 4, applied through the .article-content class. The editor surface and the preview both use it, so what the owner writes looks like what a public site would roughly show. The measure is capped at 42 rem, about 70 characters per line.

Choosing lime plaster for old stone walls

Cement traps moisture in solid walls. Lime lets the stone breathe, which is why we strip it back on almost every farmhouse we take on.

What we use
  • Hot-mixed lime for the base coat
  • Hair or fibre for the scratch coat
  • A thin lime putty finish
Drying time
It sets slowly, and that is the point.
Before you start
  1. Strip loose material back to sound stone.
  2. Wet the wall the evening before.
Article image
The north wall after the second coat.
Elementmd and upBelow md, spacing
{{ t.el }}{{ t.desk }}{{ t.rest }}

Spacing, radius and density

Spacing uses Tailwind's 4 px base unit unchanged. Radius is 0 everywhere: setting --ui-radius: 0rem flattens every component that derives its corners from it, and rounded-none overrides cover the few that hard-code rounded-full. The density is compact on desktop. On touch screens, every tap target is at least 44 px.

{{ s.k }}{{ s.px }} · {{ s.use }}
ControlHeight and use
size="sm"28 px · table row actions, toolbar buttons in the editor
size="md"32 px · default on desktop: buttons, inputs, selects, tabs
size="lg"40 px · auth forms, primary actions in dialogs
size="xl"44 px · everything below md, via a responsive size prop
Table row44 px on desktop, 64 px cards on mobile
Gutters16 px on mobile, 24 px on desktop; sidebar 224 px, collapses to 56 px

Borders and elevation

Most surfaces are flat and separated by hairlines. Shadows appear only on things that float above the page.

Hairline1 px --ui-border. Cards, table edges, sidebar and top bar dividers. Decorative, so no contrast requirement.
Search by title
Control edge1 px --ui-border-accented. Inputs, selects, checkboxes, outline buttons. 3.6:1 on white.
New article
Focus ring2 px --ui-primary outline with a 2 px offset, shown only on :focus-visible. Nuxt UI's default, kept.
Edit
Unpublish
Popover--shadow-popover. Dropdown menus, selects, toasts. In dark mode it becomes a darker shadow plus the hairline.
Modal--shadow-modal over a 40% chalk-950 overlay. Modals and slideovers.
LayerzContents
{{ z.n }}{{ z.v }}{{ z.u }}
BreakpointMinWhat changes
{{ b.n }}{{ b.v }}{{ b.u }}

Motion

Motion is there to show where something came from or that something is working. It is short and never decorative.

120 ms--duration-fast · ease-standardHover and pressed colors, focus ring, the counter turning to warning, the switch thumb.
180 ms--duration-base · ease-enter / ease-exitDropdowns and tooltips (fade plus a 4 px shift), the tab indicator, toasts sliding in, SaveStatus crossfades.
240 ms--duration-slow · ease-enter / ease-exitModals (fade plus scale from 0.98), slideovers (slide from the edge), sidebar collapse.
Never animatesRoute changes, table rows sorting or filtering, numbers counting up, the logo, editor text, and anything that runs on page load.
Reduced motionWith prefers-reduced-motion: reduce, every transition and animation completes instantly, skeletons stop pulsing and become flat blocks, and toasts appear without sliding. The one exception is the spinner on the automatic verification screen. It keeps turning, slowed to 1.6 s per rotation, because it is the only sign that work is happening.

Icons

Lucide through Iconify, using Nuxt UI's i-lucide-* classes. Icons are 16 px next to 13–14 px text and 20 px on mobile top bars. They are always paired with a visible label or an aria-label. Each icon maps to one meaning: Eye is only ever show password, and Preview uses Book Open.

{{ i.a }}{{ i.n }}

Where Nuxt UI defaults bend

{{ b.w }}{{ b.r }}

Files

Ready to paste into the repository. They follow its code style: tabs, no semicolons, single quotes and no comments. The CSS goes in src/assets/main.css and the config in src/theme/ui.config.ts. Add class="isolate" to the app root, as Nuxt UI requires.

{{ code }}